home *** CD-ROM | disk | FTP | other *** search
/ X User Tools / X User Tools (O'Reilly and Associates)(1994).ISO / sources / spacebar / spatches < prev   
Text File  |  1994-09-27  |  11KB  |  327 lines

  1. The diffs below are patches to the MIT X11R5 server source that allow
  2. you to use the spacebar of your keyboard both as a spacebar and as a
  3. control key--if you press and release it you get a space, but if you
  4. press it and hold it down while pressing other keys, it acts like the
  5. Ctrl key.
  6.  
  7. The patches are short; they are at the end of this message.  The
  8. following paragraphs explain the patches.  I've also placed this file on
  9. export.lcs.mit.edu. It is available for anonymous ftp as
  10. contrib/spacebar_hack.patches.
  11.  
  12. BUT WHY?
  13.  
  14. I've begun to have discomfort typing; it is worst twisting my wrist side
  15. to side to hit Return, Backspace, and Ctrl.  I've been training myself
  16. to use Ctrl-H instead of Backspace and Ctrl-J instead of Return, but
  17. that still leaves the Ctrl key to contend with (I'm an emacs user, so I
  18. have to use Ctrl a lot).  I've been researching alternative keyboards,
  19. and was impressed with the Kinesis keyboard which has a number of thumb
  20. buttons other than a space bar.  By default these buttons are bound to
  21. Return, Backspace, and other frequently used keys that require
  22. stretching.  I decided to see if I could simulate some of this in
  23. software.  Now that I can use my spacebar as a Ctrl key, I rarely have
  24. to stretch my wrists from side to side.  I'm releasing the patches for
  25. anyone else who finds them useful.
  26.  
  27. HOW WELL DOES IT WORK?
  28.  
  29. It reduces the discomfort I feel while typing, which was my primary
  30. goal.  It took me only a day or so to train myself to use this new Ctrl
  31. key.  A bigger problem, though is learning that when I want a Space
  32. character I've got to fully release the spacebar before typing the next
  33. character, or I'll get a control character instead.  For example, in
  34. emacs, if I try to type the words "about the" too quickly I get
  35. "abotuhe"--the " t" turns into a Ctrl-t which transposes the last two
  36. charaters of "about", and then I type "he".  It took me three or four
  37. days to get used to this, and I still do it sometime.  I don't know if
  38. this is a typing habit that other people would have as well, or if it is
  39. just something about the way I type.
  40.  
  41. This patch does seem to introduce a bug:  with this server running, I
  42. can still select text in xterm, but once selected, the text does not
  43. remain highlighted.  It can still be pasted, but you just don't get a
  44. visual indication of what text is selected in xterm.  I've got no clue
  45. why this is happening, and haven't tried to track it down; the bug
  46. doesn't bother me enough to worry about it.
  47.  
  48. I've only tried building this patch on a Sun 3 with SunOS 4.1.  It is a
  49. very short patch, and does not touch any of the device-dependent code in
  50. the server, so I expect that it should be portable to most
  51. architectures. 
  52.  
  53. I hope that you find this patch useful, but please don't ask me to
  54. provide support for it--I'm not an X server guru, and have too many
  55. other things to be working on.  The patch is provides as-is, of course,
  56. and without warranties of any kind.
  57.  
  58. HOW DO I PATCH MY SERVER?
  59.  
  60. To apply the diffs in this message to your server sources, run them
  61. through the patch program.  Do something like this:
  62.  
  63.     cd /usr/X11R5/mit
  64.     patch < keyhack.patches
  65.  
  66. Only two files are changed:  server/dix/events.c and server/os/utils.c
  67.  
  68. If your build tree hasn't been cleaned up, you may be able to rebuild
  69. the server by doing the following:
  70.  
  71.     cd server
  72.     make
  73.  
  74. But probably you'll have to do something like:
  75.  
  76.     make Makefiles
  77.     make includes
  78.     cd server
  79.     make
  80.  
  81. If you can't figure this out, talk to whoever it was that built your
  82. server to begin with.
  83.  
  84. Before installing the new server, you probably want to mv your old
  85. server to some other name.  Don't overwrite it, in case you don't like
  86. using these patches.
  87.  
  88. HOW DO I USE IT?
  89.  
  90. The new server you have just built will behave just like your old
  91. server, unless you start it with the -keyhack option.  The keyhack
  92. option takes two integer arguments: the keycode of the spacebar and the
  93. keycode of the ctrl key.  There is probably some portable way to figure
  94. this out within the X server, but I didn't know what it was, and since I
  95. didn't want to hardcode these numbers into the patch, you have to supply
  96. them on the command line.  You can figure out the keycodes for these
  97. keys with the following command which prints the keycodes for each key
  98. on your keyboard.
  99.  
  100.     xmodmap -pk | more
  101.  
  102. So, for example, I start up my server with the command:
  103.  
  104.     Xsun -zaphod -keyhack 128 83
  105.  
  106. (-zaphod is a Sun-specific option; nothing to do with this patch.)
  107.  
  108. I use xinit to start up my server, and since I don't want to type these
  109. options every time, I've created a ~/.xserverrc file with this line in
  110. it:
  111.  
  112. /usr/bin/X11/Xsun -zaphod -keyhack 128 83
  113.  
  114. If you use xdm to start up your server, there is presumably a similar
  115. configuration file you can use, but I don't know what it is.
  116.  
  117. Once you've started up the server, the spacebar hack will be active.  If
  118. someone else sits down at your machine, however, you may want to turn it
  119. off for them.  Part of this patch is to make the server respond to the
  120. SIGUSR2 signal.  If you do:
  121.  
  122.     kill -USR2 <pid>
  123.  
  124. you can turn this spacebar feature on and off.  <pid> in the above
  125. refers to the process id of the server. You'll have to do a 'ps a' to
  126. find it, or a 'ps aux' if the server was started by xdm rather than by
  127. you.  
  128.  
  129. Note that since the -keyhack argument takes two arbitrary keycodes, you
  130. could use this patch to make your Return key act like Return and Meta,
  131. or whatever else.
  132.  
  133. TODO
  134.  
  135. The right way to have introduced this functionality would really have
  136. been as a server extension, probably integrated with the X Input
  137. extension in some way.  Then there could be extended protocol requests
  138. to turn the feature on and off, instead of relying on a SIGUSR2, and
  139. there would presumably be a way to not have to pass keycodes on the
  140. command line.  I'll leave these changes to someone who is more familiar
  141. with the X server internals than I am.
  142.  
  143. Share and enjoy!
  144.  
  145.     David Flanagan
  146.     david@ora.com
  147.  
  148.  
  149. Patches are below this line.
  150. ----------------------------------------------------------------------
  151. *** server/dix/events.c.orig    Wed Jun  2 22:27:40 1993
  152. --- server/dix/events.c    Sun Jul  4 18:42:53 1993
  153. ***************
  154. *** 1813,1818 ****
  155. --- 1813,1822 ----
  156.       }
  157.   }
  158.   
  159. + int hack_space_keycode;  /* set from the command line */  
  160. + int hack_ctrl_keycode;
  161. + int keyhack_on;
  162.   void
  163.   ProcessKeyboardEvent (xE, keybd, count)
  164.       register xEvent *xE;
  165. ***************
  166. *** 1827,1832 ****
  167. --- 1831,1838 ----
  168.       GrabPtr         grab = keybd->grab;
  169.       Bool            deactivateGrab = FALSE;
  170.       register KeyClassPtr keyc = keybd->key;
  171. +     static int state;  /* state for a simple FSM */
  172. +     int oldkey;
  173.   
  174.       if (!syncEvents.playingEvents)
  175.       NoticeTime(xE)
  176. ***************
  177. *** 1841,1846 ****
  178. --- 1847,1901 ----
  179.       switch (xE->u.u.type)
  180.       {
  181.       case KeyPress: 
  182. +         if (keyhack_on) {
  183. +         switch (state) {
  184. +         case 0:
  185. +             /* eat space down events and go to state 1.
  186. +              * process all other key presses normally.
  187. +              * If Ctrl is already down, treat space normally.
  188. +              * this is a special case for Ctrl-Space, used in emacs.
  189. +              */
  190. +             if ((key == hack_space_keycode) &&
  191. +             !(keyc->state & ControlMask))
  192. +             {
  193. +             state = 1;
  194. +             return;
  195. +             }
  196. +             break;
  197. +             
  198. +         case 1:
  199. +             /* send a Ctrl-down event, go to state 2 and
  200. +              * fall through to the next case.  Set state
  201. +              * to a meaningless value while recursing so we
  202. +              * don't get any special processing for the
  203. +              * synthesized events.
  204. +              */
  205. +             state = -1;
  206. +             oldkey = xE->u.u.detail;
  207. +             xE->u.u.detail = hack_ctrl_keycode;
  208. +             ProcessKeyboardEvent(xE, keybd, count);
  209. +             xE->u.u.detail = oldkey;
  210. +             state = 2;
  211. +             
  212. +         case 2:
  213. +             /*
  214. +              * pass any key down event through, but set the Ctrl
  215. +              * modifier on it.  We can set the Ctrl modifier by just
  216. +              * recomputing the state field of the event as we did
  217. +              * above.  This is in fact more general, and will work
  218. +              * with other modifier keys as well.  This works because
  219. +              * when we sent the fake Ctrl down event above, the
  220. +              * recursive call to ProcessKeyboardEvent will change
  221. +              * keyc->state.
  222. +              * The only time we leave this state is on a key up
  223. +              * event below.
  224. +              */
  225. +             xE->u.keyButtonPointer.state =
  226. +             (keyc->state | inputInfo.pointer->button->state);
  227. +             break;
  228. +         }
  229. +         }
  230.           if (*kptr & bit) /* allow ddx to generate multiple downs */
  231.           {   
  232.           if (!modifiers)
  233. ***************
  234. *** 1872,1877 ****
  235. --- 1927,1971 ----
  236.           }
  237.           break;
  238.       case KeyRelease: 
  239. +         if (keyhack_on) {
  240. +         switch (state) {
  241. +         case 0:
  242. +             /* key releases are handled normally in this state */
  243. +             break;
  244. +         case 1:
  245. +             /*
  246. +              * if we get a space up before any other key down
  247. +              * keystroke, then we send space up, down and return to
  248. +              * state 0.  Set state to a meaningless value while
  249. +              * recursing so we don't process our own fake events.
  250. +              */
  251. +             if (key == hack_space_keycode) {
  252. +             state = -1;
  253. +             xE->u.u.type = KeyPress;
  254. +             ProcessKeyboardEvent(xE, keybd, count);
  255. +             xE->u.u.type = KeyRelease;
  256. +             ProcessKeyboardEvent(xE, keybd, count);
  257. +             state = 0;
  258. +             return;
  259. +             }
  260. +             break;
  261. +         case 2:
  262. +             /*
  263. +              * if this is a space up, convert it to a Ctrl up, 
  264. +              * send it, and revert to state 0.  Otherwise, just
  265. +              * send it as is and stay in this state.
  266. +              */
  267. +             if (key == hack_space_keycode) {
  268. +             state = -1;
  269. +             xE->u.u.detail = hack_ctrl_keycode;
  270. +             ProcessKeyboardEvent(xE, keybd, count);
  271. +             state = 0;
  272. +             return;
  273. +             }
  274. +             break;
  275. +         }
  276. +         }
  277.           if (!(*kptr & bit)) /* guard against duplicates */
  278.           return;
  279.           inputInfo.pointer->valuator->motionHintWindow = NullWindow;
  280. *** server/os/utils.c.orig    Thu Jun  3 14:28:34 1993
  281. --- server/os/utils.c    Thu Jun  3 12:34:53 1993
  282. ***************
  283. *** 240,245 ****
  284. --- 240,252 ----
  285.       ddxUseMsg();
  286.   }
  287.   
  288. + SIGVAL
  289. + hacktoggle()
  290. + {
  291. +     extern int keyhack_on;
  292. +     keyhack_on = !keyhack_on;
  293. + }
  294.   /*
  295.    * This function parses the command line. Handles device-independent fields
  296.    * and allows ddx to handle additional fields.  It is not allowed to modify
  297. ***************
  298. *** 521,526 ****
  299. --- 528,550 ----
  300.               SyncOn++;
  301.           }
  302.   #endif
  303. +     else if (strcmp(argv[i], "-keyhack") == 0) {
  304. +         extern int hack_space_keycode;
  305. +         extern int hack_ctrl_keycode;
  306. +         extern int keyhack_on;
  307. +         if (i < argc-1) {
  308. +         hack_space_keycode = atoi(argv[++i]);
  309. +         hack_ctrl_keycode = atoi(argv[++i]);
  310. +         keyhack_on = 1;
  311. +         signal(SIGUSR2, hacktoggle);
  312. +         }
  313. +         else {
  314. +         fprintf(stderr,
  315. +             "-keyhack argument needs two integer values.\n");
  316. +         keyhack_on = 0;
  317. +         }
  318. +     }
  319.        else
  320.        {
  321.           UseMsg();
  322.